home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / DocShell / ODDocRef.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  13.5 KB  |  509 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODDocRef.cpp
  3.  
  4.     Contains:    Implementation of ODDocRef.h
  5.  
  6.                 This class is meant to replace the routines in DocUtils.cpp and
  7.                 provide a much more robust mechanism for opening OpenDoc files
  8.                 and displaying drafts.
  9.  
  10.     Owned by:    Nick Pilch
  11.  
  12.     Copyright:    
  13.  
  14.     Change History (most recent first):
  15.  
  16.          <5>     10/5/96    TJ        1392437 Fixed read/write permissions.
  17.          <4>     10/5/96    NP        Comments concerning changes to DocUtils.
  18.          <3>    27.09.1996    NP        1386083: Removed some code.
  19.          <2>    20.09.1996    NP        1386083: Rewrite document opening code.
  20.          <1>    18.09.1996    NP        first checked in
  21.  
  22.     To Do:
  23. */
  24.  
  25. #ifndef _ODDOCREF_
  26. #include "ODDocRef.h"
  27. #endif
  28.  
  29. #ifndef _PLFMFILE_
  30. #include "PlfmFile.h"
  31. #endif
  32.  
  33. #ifndef _DOCUTILS_
  34. #include "DocUtils.h"
  35. #endif
  36.  
  37. #ifndef _STORUTIL_
  38. #include "StorUtil.h"
  39. #endif
  40.  
  41. #ifndef _TEMPOBJ_
  42. #include "TempObj.h"
  43. #endif
  44.  
  45.  
  46. #ifndef _DOCUTILP_
  47. #include "DocUtilP.h"
  48. #endif
  49.  
  50.  
  51. #ifndef SOM_ODSession_xh
  52. #include <ODSessn.xh>
  53. #endif
  54.  
  55. #ifndef SOM_ODDraft_xh
  56. #include <Draft.xh>
  57. #endif
  58.  
  59. #ifndef SOM_ODDocument_xh
  60. #include <Document.xh>
  61. #endif
  62.  
  63. #ifndef SOM_ODObjectNameSpace_xh
  64. #include "ObjectNS.xh"
  65. #endif
  66.  
  67. #ifndef SOM_ODNameSpaceManager_xh
  68. #include <NmSpcMg.xh>
  69. #endif
  70.  
  71. #ifndef SOM_ODContainer_xh
  72. #include <ODCtr.xh>
  73. #endif
  74.  
  75. #ifndef SOM_ODWindowState_xh
  76. #include <WinStat.xh>
  77. #endif
  78.  
  79. #ifndef SOM_ODDispatcher_xh
  80. #include <Disptch.xh>
  81. #endif
  82.  
  83. #ifndef SOM_ODLinkManager_xh
  84. #include <LinkMgr.xh>
  85. #endif
  86.  
  87.  
  88. #include <stdio.h>
  89.  
  90.  
  91.  
  92. const ODISOStr        kODRefNumDocument            =    "RefNumDocument";
  93. const ODISOStr        kODDocumentTempDraft        =    "DocumentTempDraft";
  94.  
  95.  
  96.  
  97.  
  98. static ODFileRefNum DeduceRefNum(PlatformFile* file, 
  99.                                     ODULong prevRefNumCount,
  100.                                     ODSShort* prevRefNums);
  101. static void CreateISOStrKeyFromULong(ODULong uLongKey, char str[9]);
  102.  
  103.  
  104. //------------------------------------------------------------------------------
  105. // ODOpenDocumentRef::ODOpenDocumentRef
  106. //------------------------------------------------------------------------------
  107.  
  108. ODOpenDocumentRef::ODOpenDocumentRef(ODSession*         session,
  109.                                     PlatformFile*         document,
  110.                                     ODDraftPermissions    permissions)
  111. {
  112.     WASSERT(session != kODNULL);
  113.     WASSERT(document != kODNULL);
  114.     
  115.     fSession = session;
  116.     fFile = document;
  117.     fPermissions = permissions;
  118.     
  119.     fContainer = kODNULL;
  120.     fDocument = kODNULL;
  121.     fRefNum = 0;
  122.     fTempDraft = kODNULL;
  123.     fNameSpaceManager = kODNULL;
  124. }
  125.  
  126. //------------------------------------------------------------------------------
  127. // ODOpenDocumentRef::~ODOpenDocumentRef
  128. //------------------------------------------------------------------------------
  129.  
  130. ODOpenDocumentRef::~ODOpenDocumentRef()
  131. {
  132. //    PlatformFile::IsOpenDocDocument('xxxx','xxxx');
  133. }
  134.  
  135. //------------------------------------------------------------------------------
  136. // DeduceRefNum
  137. //------------------------------------------------------------------------------
  138.  
  139. static ODFileRefNum DeduceRefNum(PlatformFile* file, 
  140.                                     ODULong prevRefNumCount,
  141.                                     ODSShort* prevRefNums)
  142. {
  143.     ODFileRefNum    retval = 0;
  144.     ODULong         newRefNumCount = 0;
  145.     ODSShort*         newRefNums = kODNULL;
  146.  
  147.     file->GetLocalPaths(kODDataFork, &newRefNumCount, &newRefNums);
  148.  
  149.     WASSERT(newRefNumCount == prevRefNumCount + 1);
  150.  
  151.     ODULong i = 0,j;
  152.     ODBoolean found = kODFalse;
  153.     
  154.     while  (i<newRefNumCount)
  155.     {
  156.         j = 0;
  157.         while (j<prevRefNumCount && (found = (newRefNums[i] == prevRefNums[j]))==kODFalse)
  158.             ++j;
  159.         if (!found)
  160.             break;
  161.         ++i;
  162.     }
  163.     
  164.     WASSERT(i<newRefNumCount);
  165.     
  166.     retval = newRefNums[i];
  167.     
  168.     if (newRefNums) 
  169.         ODDisposePtr((Ptr)newRefNums);
  170.  
  171.     return retval;
  172. }
  173.  
  174. //------------------------------------------------------------------------------
  175. // ODOpenDocumentRef::Open
  176. //
  177. // acquires top draft
  178. // acquires top draft again and temp draft if it's a read/write document.
  179. //------------------------------------------------------------------------------
  180.  
  181. ODDraft* ODOpenDocumentRef::Open(Environment* ev)
  182. {
  183.     ODDraft*        currentDraft = kODNULL;
  184.     ODULong            refNumCount, i;
  185.     ODSShort*        refNums = kODNULL;
  186.     ODError            error = kODNoError;
  187.  
  188.     ODVolatile(currentDraft);
  189.     ODVolatile(refNums);
  190.     ODVolatile(fTempDraft);
  191.  
  192.     fNameSpaceManager = fSession->GetNameSpaceManager(ev);
  193.  
  194.     TRY
  195.         ODDocument*        document = kODNULL;
  196.  
  197.         refNumCount = 0;
  198.         fFile->GetLocalPaths(kODDataFork, &refNumCount, &refNums);
  199.     
  200.         // ACQUIRING ALREADY OPEN DRAFT BECAUSE WE HAVE TO RELEASE IT WHERE??????????
  201.         //    NP: I have yet to see this code executed. When does it?
  202.         for ( i=0; i<refNumCount; ++i)
  203.         {
  204.             if ((document = ODGetOpenDocumentFromRefNum(ev, fSession, refNums[i])) != kODNULL)
  205.             {
  206.                 WARN("This really happens!");
  207.                 currentDraft = ODGetTempDraftFromOpenDocument(ev, fSession, document);
  208.                 if (currentDraft)
  209.                     currentDraft->Acquire(ev);
  210.                 else
  211.                     currentDraft = document->AcquireDraft(ev,kODDPReadOnly,0,kODNULL,kODPosTop,kODFalse);
  212.                 if (refNums)
  213.                     ODDisposePtr(refNums);
  214.                 return currentDraft;         // exit point
  215.             }
  216.         }
  217.  
  218.         // reusing currentDraft variable here
  219.         currentDraft = this->AcquireCtrDocTopDraft(ev);
  220.         // AcquireCtrDocTopDraft opens the file and adds a new refnum, so we
  221.         //    should be able to deduce it.
  222.         fRefNum = DeduceRefNum(fFile, refNumCount, refNums);
  223.  
  224.     CATCH_ALL
  225.         error = ErrorCode();
  226.         if (currentDraft)
  227.             ODFinalReleaseObject(ev, currentDraft);
  228.         ODFinalReleaseObject(ev, fDocument);
  229.         ODFinalReleaseObject(ev, fContainer);
  230.         // We will reraise right below after freeing memory.
  231.     ENDTRY
  232.  
  233.     // Make sure to free memory
  234.     if (refNums)
  235.         ODDisposePtr(refNums);
  236.  
  237.     // reraise here
  238.     THROW_IF_ERROR(error);
  239.  
  240.     TRY
  241.         // Create temp draft for doc with write permissions.
  242.         if (HAS_WRITE_ACCESS(fPermissions) && !fFile->IsLocked())
  243.         {
  244.             // draft acquire
  245.             currentDraft = 
  246.                 fDocument->AcquireDraft(ev, fPermissions, 0, currentDraft,
  247.                                         kODPosSame, kODTrue);
  248.             // new refcount is still 1.
  249.             currentDraft = fDocument->CreateDraft(ev, currentDraft, kODTrue);
  250.             // former top draft now released and new draft has refCount of 1
  251.             // draft acquire
  252.             // Because "The caller is responsible for properly refcounting
  253.             //    the temp draft."
  254.             // From DocUtils.h documentation of ODDocumentOpened.
  255.             currentDraft->Acquire(ev);
  256.             // top draft refcount now 2, will get released in
  257.             //    RealShell::OpenFile
  258.             // set instance variable
  259.             fTempDraft = currentDraft;
  260.         }
  261.  
  262.         this->DocumentOpened(ev);
  263.     CATCH_ALL
  264.         if (fTempDraft)
  265.         {
  266.             // Need to call release twice. Don't use ODReleaseObject.
  267.             fTempDraft->Release(ev); 
  268.             ODFinalReleaseObject(ev, fTempDraft);
  269.         }
  270.         else
  271.             ODFinalReleaseObject(ev, currentDraft);
  272.         ODFinalReleaseObject(ev, fDocument);
  273.         ODFinalReleaseObject(ev, fContainer);
  274.         RERAISE;
  275.     ENDTRY
  276.  
  277.     // We don't have to worry about ODDocumentOpened anymore.
  278.  
  279.     // Want to release these here, because ODDocumentOpened will acquire
  280.     //    them!!!!! ODDocumentOpened wants to be balanced with
  281.     //    ODDocumentClosed. (These multiple-purpose utilities are called in other
  282.     //    contexts, so which it's important to preserve semantics.)
  283. //    TempODContainer tempCont = fContainer; // container release
  284. //    TempODDocument  tempDoc  = fDocument;    //    document release
  285.  
  286.     return currentDraft;
  287. }
  288.  
  289. //------------------------------------------------------------------------------
  290. // ODOpenDocumentRef::OpenDraft
  291. //------------------------------------------------------------------------------
  292.  
  293. void ODOpenDocumentRef::OpenDraft(Environment* ev, ODDraft* draft)
  294. {
  295.     // Just calling the utility because there's no changes I want to make to
  296.     //    ODOpenDraft at
  297.     //    this time. I believe that the ODWindowState calls made in need to be
  298.     //    revved. They need to be able to completely clean up after themselves.
  299.     //    This includes closing all windows and releasing any parts that they
  300.     //    created.
  301.     ODOpenDraft(ev, fSession, draft);
  302. }
  303. #if 0
  304. //------------------------------------------------------------------------------
  305. // ODOpenDocumentRef::Save
  306. //------------------------------------------------------------------------------
  307.  
  308. void ODOpenDocumentRef::Save(Environment* ev)
  309. {
  310. }
  311.  
  312. //------------------------------------------------------------------------------
  313. // ODOpenDocumentRef::Close
  314. //------------------------------------------------------------------------------
  315.  
  316. void ODOpenDocumentRef::Close(Environment* ev)
  317. {
  318. }
  319.  
  320. //------------------------------------------------------------------------------
  321. // ODOpenDocumentRef::GetDocument
  322. //------------------------------------------------------------------------------
  323.  
  324. ODDocument* ODOpenDocumentRef::GetDocument()
  325. {
  326.     return 0;
  327. }
  328.  
  329. //------------------------------------------------------------------------------
  330. // ODOpenDocumentRef::GetTopDraft
  331. //------------------------------------------------------------------------------
  332.  
  333. ODDraft* ODOpenDocumentRef::GetTopDraft()
  334. {
  335.     return 0;
  336. }
  337. #endif /* 0 */
  338. //------------------------------------------------------------------------------
  339. // ODOpenDocumentRef::AcquireCtrDocTopDraft
  340. //
  341. // acuires container and document and draft returned
  342. //------------------------------------------------------------------------------
  343.  
  344. ODDraft* ODOpenDocumentRef::AcquireCtrDocTopDraft(Environment* ev)
  345. {
  346.     ODDraft*    draft = kODNULL;
  347.  
  348.     TRY
  349.         fContainer = AcquireFileContainer(ev, fSession, &(fFile->GetFileSpec()));
  350.         fDocument = fContainer->AcquireDocument(ev, kODDefaultDocument);
  351.         draft = fDocument->AcquireDraft(ev, kODDPReadOnly, 0, kODNULL, kODPosTop,
  352.                                             kODFalse);
  353.     CATCH_ALL
  354.         if (fDocument)
  355.             ODFinalReleaseObject(ev, fDocument);
  356.         if (fContainer)
  357.             ODFinalReleaseObject(ev, fContainer);
  358.         RERAISE;
  359.     ENDTRY
  360.     
  361.     return draft;
  362. }
  363.  
  364. //------------------------------------------------------------------------------
  365. // CreateISOStrKeyFromULong
  366. //------------------------------------------------------------------------------
  367.  
  368. static void CreateISOStrKeyFromULong(ODULong    uLongKey, char str[9])
  369. {
  370.     sprintf(str,"%.8lX",uLongKey);
  371. }
  372.  
  373. //------------------------------------------------------------------------------
  374. // ODOpenDocumentRef::DocumentOpened
  375. //
  376. //
  377. //------------------------------------------------------------------------------
  378.  
  379. void ODOpenDocumentRef::DocumentOpened(Environment* ev)
  380. {
  381.     // document acquire
  382. //    fDocument->Acquire(ev);    // Balanced by Release in ODDocumentClosed.
  383.     // container acquire
  384. //    fDocument->GetContainer(ev)->Acquire(ev); // Balanced by Release in
  385.                                                 //    ODDocumentClosed.
  386.  
  387.     this->AddToRefNumDocNS(ev);
  388.  
  389.     if (fTempDraft)
  390.     {
  391.         TRY
  392.             this->AddToTempDraftNS(ev);
  393.         CATCH_ALL
  394.             this->RemoveFromRefNumDocNS(ev);
  395.             RERAISE;
  396.         ENDTRY
  397.     }
  398. }
  399.  
  400. //------------------------------------------------------------------------------
  401. // ODOpenDocumentRef::AddToRefNumDocNS
  402. //------------------------------------------------------------------------------
  403.  
  404. void ODOpenDocumentRef::AddToRefNumDocNS(Environment* ev)
  405. {
  406.     ODObjectNameSpace* nameSpace = 
  407.         (ODObjectNameSpace*)fNameSpaceManager->HasNameSpace( ev, 
  408.                                                         kODRefNumDocument);
  409.     if (!nameSpace)
  410.     {
  411.         nameSpace = 
  412.             (ODObjectNameSpace*)fNameSpaceManager->CreateNameSpace(
  413.                 ev, kODRefNumDocument, kODNULL, 5, kODNSDataTypeODObject);
  414.     }
  415.     
  416.     {
  417.         char key[9];
  418.         CreateISOStrKeyFromULong((ODULong)fRefNum, key);
  419. #if ODDebug
  420.         ODDocument* unusedDocument;
  421.         if (nameSpace->GetEntry(ev, key, (ODObject**)&unusedDocument))
  422.             WARN("refnum already in kODRefNumDocument namespace!");
  423. #endif
  424.         nameSpace->Register(ev, key, fDocument);
  425.     }
  426.  
  427. }
  428.  
  429. //------------------------------------------------------------------------------
  430. // ODOpenDocumentRef::RemoveFromRefNumDocNS
  431. //------------------------------------------------------------------------------
  432.  
  433. void ODOpenDocumentRef::RemoveFromRefNumDocNS(Environment* ev)
  434. {
  435.     ODObjectNameSpace* nameSpace = 
  436.         (ODObjectNameSpace*)fNameSpaceManager->HasNameSpace( ev, 
  437.                                                         kODRefNumDocument);
  438.     if (nameSpace)
  439.     {
  440.         char key[9];
  441.         CreateISOStrKeyFromULong((ODULong)fRefNum, key);
  442. #if ODDebug
  443.         ODDocument* unusedDocument;
  444.         if (!nameSpace->GetEntry(ev, key, (ODObject**)&unusedDocument))
  445.             WARN("refnum not in kODRefNumDocument namespace!");
  446. #endif
  447.         nameSpace->Unregister(ev, key);
  448.     }
  449. }
  450.  
  451. //------------------------------------------------------------------------------
  452. // ODOpenDocumentRef::AddToTempDraftNS
  453. //------------------------------------------------------------------------------
  454.  
  455. void ODOpenDocumentRef::AddToTempDraftNS(Environment* ev)
  456. {
  457.     ODNameSpaceManager* fNameSpaceManager = fSession->GetNameSpaceManager(ev);
  458.  
  459.     ODObjectNameSpace* nameSpace =    
  460.         (ODObjectNameSpace*)fNameSpaceManager->HasNameSpace( ev, 
  461.                                                         kODDocumentTempDraft);
  462.     if (!nameSpace)
  463.     {
  464.         nameSpace = 
  465.             (ODObjectNameSpace*)fNameSpaceManager->CreateNameSpace(
  466.                 ev, kODDocumentTempDraft, kODNULL, 5, kODNSDataTypeODObject);
  467.     }
  468.     
  469.     {
  470.         char key[9];
  471.         CreateISOStrKeyFromULong((ODULong)fDocument, key);
  472.         ODDraft* unusedDraft;
  473.         if (nameSpace->GetEntry(ev, key, (ODObject**)&unusedDraft))
  474.         {
  475.             WARN("There was a temp draft already in this namespace???");
  476.             nameSpace->Unregister(ev, key);
  477.         }
  478.         nameSpace->Register(ev, key, fTempDraft);
  479.     }
  480. }
  481.  
  482. //------------------------------------------------------------------------------
  483. // ODOpenDocumentRef::RemoveFromTempDraftNS
  484. //
  485. // not currently needed because the last thing that ::Open does is to add to
  486. //    temp draft NS. If that fails, then it doesn't need to be undone.
  487. //------------------------------------------------------------------------------
  488. #if 0
  489. void ODOpenDocumentRef::RemoveFromTempDraftNS(Environment* ev)
  490. {
  491.     ODNameSpaceManager* fNameSpaceManager = fSession->GetNameSpaceManager(ev);
  492.  
  493.     ODObjectNameSpace* nameSpace =    
  494.         (ODObjectNameSpace*)fNameSpaceManager->HasNameSpace( ev, 
  495.                                                         kODDocumentTempDraft);
  496.     if (nameSpace)
  497.     {
  498.         char key[9];
  499.         CreateISOStrKeyFromULong((ODULong)fDocument, key);
  500.         ODDraft* unusedDraft;
  501. #if ODDebug
  502.         if (!nameSpace->GetEntry(ev, key, (ODObject**)&unusedDraft))
  503.             WARN("No temp draft to remove!");
  504. #endif
  505.         nameSpace->RemoveEntry(ev, key, fTempDraft);
  506.     }
  507. }
  508. #endif /* 0 */
  509.